package com.swdegao.iot.netty.server.qianbaotonghandler;

import com.alibaba.fastjson.JSON;
import com.swdegao.iot.SwdegaoIotMgtServerApplication;
import com.swdegao.iot.netty.entity.*;
import com.swdegao.iot.netty.utils.ConvertUtils;
import com.swdegao.iot.netty.utils.RedisUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.binary.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;


@Slf4j
public class QianBaoTong_ParseMessgaeHandler extends SimpleChannelInboundHandler<Object>{

	@Autowired
	private RedisUtils redisUtils = SwdegaoIotMgtServerApplication.getBean(RedisUtils.class);
	static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
//	private HandlerMessage hm = new HandlerMessage();
	@SuppressWarnings("unused")
	private String tempTime = null;//用于比较心跳是否超时

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { // (4)
		ByteBuf in = (ByteBuf)msg;
		byte[] barray = new byte[in.readableBytes()];
		in.getBytes(0,barray);
		log.info("parse 获取到数据："+Hex.encodeHexString(barray));
		byte[] concentratorAddrArray = Arrays.copyOfRange(barray, 4, 15);
		String concentratorAddr = StringUtils.newStringUsAscii(concentratorAddrArray);//终端地址
		byte[] controlCodeArray = Arrays.copyOfRange(barray, 25, 28);
		String controlCode = Hex.encodeHexString(controlCodeArray);//控制码

		try{
			if (!QianBaoTong_Const.hasChannelID(concentratorAddr)) {
				String uuid = QianBaoTong_Const.isChannel(ctx.channel());//获取上线时设置的uuid
				QianBaoTong_Const.ChangeClientId(uuid, concentratorAddr);//把UUDI换成通讯地址
			}
			// 检查重复链接ID 不同实例 切换实例
			if (QianBaoTong_Const.ischangeChannelID(concentratorAddr, ctx.channel())) {
				QianBaoTong_Const.changeChannel(concentratorAddr, ctx.channel());
			}
			switch (controlCode) {
				case "555555"://从到主，采集完成应答
					//集中器采集完成后，第一次请求户表数据
					byte[] firstDataCommand = QianBaoTong.encodeReadingCommand(concentratorAddr,(byte) 1);
					ctx.writeAndFlush(Unpooled.wrappedBuffer(firstDataCommand));
					break;
				case "525252"://数据读取应答
					byte[] meterAddrArray = Arrays.copyOfRange(barray, 30, 36);
					String meterAddr = bcdToString(meterAddrArray);//终端地址
					if(Long.parseLong(meterAddr) == 0){
						break;//户表地址为0，则不再请求下一页
					}
					//集中器回复
					byte pageByte = barray[28];//回复的数据所在页号
					// 将十六进制字符串转换为整数
					int decimalValue = Integer.parseInt(Integer.toHexString(pageByte), 16);
					// 加1
					int incrementedValue = decimalValue + 1;//页号加1，请求下一页
					System.out.println((byte) incrementedValue);
					byte[] dataCommand = QianBaoTong.encodeReadingCommand(concentratorAddr,(byte) incrementedValue);
					ctx.writeAndFlush(Unpooled.wrappedBuffer(dataCommand));//请求下一页
					break;
				case "414141"://设置IP和端口应答
					break;
				case "545454"://刷新时钟应答
					break;
				case "505050"://定时抄表应答
					break;
				case "575757"://下载档案应答
					break;
				case "4B4B4B"://阀门打开应答
					break;
				case "474747"://阀门关闭应答
					break;
				case "4F4F4F"://采集器通道打开应答
					break;
				case "434343"://采集器通道关闭应答
					break;
			}


			CallBackData callBackData = new CallBackData();
			callBackData.setImei(concentratorAddr);
			callBackData.setCreatetime(new Date().getTime());
			callBackData.setUpData(Hex.encodeHexString(barray));
			callBackData.setTopic(Parameter.QianBaoTong_RocektMq);
			callBackData.setTag(Parameter.QianBaoTong_RocektMq_Tag);
			ctx.fireChannelRead(callBackData);
		}
		catch(Exception e){
			log.error("千宝通设备 {}：{}",concentratorAddr,e.getMessage());
		} finally {
			//ReferenceCountUtil.release(in);
			//logger.error(ChannelID+"ParseMessgaeHandlerfinally");
		}
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception { // (5)
		QianBaoTong_Const.add(String.valueOf(UUID.randomUUID()), ctx.channel());
		channels.add(ctx.channel());
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception { // (6)
//		inactiveAction(ctx);

	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (7)
		// 当出现异常就关闭连接
		cause.printStackTrace();
//		ctx.close();
	}

	private static void hexPlusOne(String hexString) throws DecoderException {

//		// 将十六进制字符串转换为整数
//		int decimalValue = Integer.parseInt(hexString, 16);
//
//		// 加1
//		int incrementedValue = decimalValue + 1;
//
//		// 将结果转换回十六进制字符串，并去掉前缀 "0x"
//		String incrementedHexString = Integer.toHexString(incrementedValue).toUpperCase();
//
//		// 打印结果
//		System.out.println("Original Hex: " + hexString);
//		System.out.println("Incremented Hex: " + incrementedHexString);
//		byte[] t = Hex.decodeHex(incrementedHexString);
//		return incrementedHexString.getBytes()[0];//控制码
		//集中器回复
		byte pageByte = (byte) 1;
		// 将十六进制字符串转换为整数
		int decimalValue = Integer.parseInt(Integer.toHexString(pageByte), 16);
		// 加1
		int incrementedValue = decimalValue + 1;
		System.out.println((byte) incrementedValue);
	}


	public static void main(String arg[]) throws DecoderException {
		hexPlusOne("256");
	}

	/**
	 * 将BCD码字节数组转换为字符串
	 *
	 * @param bcdBytes BCD码字节数组
	 * @return 对应的十进制数字字符串
	 */
	public static String bcdToString(byte[] bcdBytes) {
		StringBuilder result = new StringBuilder();

		// 遍历BCD码字节数组
		for (byte b : bcdBytes) {
			// 提取高四位表示的十进制数字
			int highNibble = (b & 0xF0) >> 4;
			// 提取低四位表示的十进制数字
			int lowNibble = b & 0x0F;

			// 将两个十进制数字添加到结果字符串中
			result.append(highNibble).append(lowNibble);
		}

		return result.toString();
	}

	/**
	 * 上线操作
	 *
	 * @param imei
	 * @param
	 */
	private void onoffLineAction(String imei, String type,int status) {
		OnOffData onOff = new OnOffData();
		onOff.setImei(imei);
		onOff.setCreatetime(System.currentTimeMillis());
		onOff.setAction(type);
		redisUtils.lPush(imei + Parameter.on_off_info, JSON.toJSONString(onOff));// 存储所有updata数据
	}
	/**
	 * 上线下线操作
	 *
	 * @param imei
	 * @param
	 */
	@SuppressWarnings("unused")
	private void onoffLineForCenter(String imei, int status) {
		Terminals terminal = new Terminals();
		terminal.setImei(imei);
		terminal.setOnlinestatus(status);
		//ts.updateTerminalOnlineStatus(terminal);
	}
	/**
	 * 下线完整操作
	 */
	private void inactiveAction(ChannelHandlerContext ctx){
		String channelId = QianBaoTong_Const.getChannelIds(ctx.channel());
		if(!"".equals(channelId) && !channelId.contains("_")){
			onoffLineAction(channelId, Parameter.offline_des,0);// 记录下线
			onoffLineForCenter(channelId,0);
			//清掉redis中关于心跳记录
			ImeiInfo imeiInfo = JSON.parseObject(redisUtils.hmGet(Parameter.imei_info,channelId).toString(), ImeiInfo.class);
			imeiInfo.setHeartbeat_delay_num(0);
			imeiInfo.setHeartbeat_registered_num(0);
			redisUtils.hmSet(Parameter.imei_info, channelId, JSON.toJSONString(imeiInfo));
		}
		QianBaoTong_Const.remove(ctx.channel());
		channels.remove(ctx.channel());
	}

	public String getTimeNow() {
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return df.format(new Date());
	}

	/**
	 * 获取超时时间
	 * @param timeNow
	 */
	public String getTimeOut(String timeNow) {
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Calendar cal = new GregorianCalendar();

		try {
			cal.setTime(df.parse(timeNow));
			cal.add(Calendar.SECOND, Parameter.outtime_hear);

		} catch (ParseException e) {
			e.printStackTrace();
		}
		return df.format(cal.getTime());
	}

	/**
	 * 比较超时时间，是否超时
	 */
	public int CompareOutTime(String timeNow,String timeAfter, SimpleDateFormat timestampFormat)
	{
        if(timeNow.equals(timeAfter)) // same
            return 1;
        try {
            Date timesN = timestampFormat.parse(timeNow);
            Date timesA = timestampFormat.parse(timeAfter);
            if(timesA.after(timesN)) // time 1 is newer
                return 1;
            else return -1;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 1;
	}

	/**
	 *
	 * @param
	 * @param
	 * @return
	 */
	public ByteBuf ToDeviceClockMsg()
     {
		 SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
		 String date = df.format(new Date());
		 byte[] temp2_ = ConvertUtils.getDateFromStrDX(date, 7);
         byte[] msg = new byte[8 + temp2_.length];
         msg[0] = (byte) 0xaa;
         msg[1] = 0x55;
         msg[2] = 0x07;
		 msg[3] = 0x00;
         msg[4] = 0x16;
		 msg[5] = 0x00;
		 msg[6] = 0x00;

         System.arraycopy(temp2_, 0, msg, 7, 7);
         msg[msg.length - 1] = ConvertUtils.getTotalForByte(msg);

         return Unpooled.wrappedBuffer(msg);
     }

	/**
	 * 四联协议统一回复
	 * @return
	 */
	public ByteBuf ToDeviceallMsg(ByteBuf buf)
	{
		byte[] b = ByteBufUtil.getBytes(buf);
		byte[] temp = new byte[5];
		System.arraycopy(b, 7, temp, 0, temp.length);
		byte[] msg = new byte[17];
		msg[0] = (byte) 0x68;
		msg[1] = 0x27;
		msg[2] = 0x00;
		msg[3] = 0x27;
		msg[4] = 0x00;
		msg[5] = 0x68;
		msg[6] = 0x0A;
		System.arraycopy(temp, 0, msg, 7, temp.length);
		msg[12] = 0x00;
		msg[13] = 0x60;
		msg[14] = 0x01;
		temp = new byte[msg.length-8];
		System.arraycopy(msg, 6, temp, 0, temp.length);
		msg[15] = ConvertUtils.getTotalForByte(temp);
		msg[16] = 0x16;
		return Unpooled.wrappedBuffer(msg);
	}


	public ByteBuf GetSuccessSignal(String imei,byte type,boolean suc) {
		byte[] msg = new byte[23];
        msg[0] = (byte) 0x80;
        msg[1] = 0x23;
        msg[2] = 0;
        msg[3] = type;
        byte[] temp = imei.getBytes();
        System.arraycopy(temp, 0, msg, 4, 15);//类型、imei
        msg[19] = (byte)(suc ? 0x73 : 0x74);//应答状态
        msg[20] = ConvertUtils.getTotalForByte(msg);//校验和
        msg[21] = 0x0d;
        msg[22] = 0x0a;
		return  Unpooled.wrappedBuffer(msg);
	}
	/**
	 * 预置命令
	 * @param imei
	 * @param presetCommand
	 * @return
	 * @throws DecoderException
	 */
	public ByteBuf GetPresetCommand(String imei,PresetCommand presetCommand) throws DecoderException {
		byte[]  downData = Hex.decodeHex(presetCommand.getDownData());
		int msg_length = 22 + downData.length;
		int msg_length_h = msg_length/100;
		int msg_length_l = msg_length -(msg_length/100)*msg_length_h;
		byte[] msg = new byte[msg_length];
        msg[0] = (byte) 0x80;
        msg[1] = (byte)Integer.parseInt(msg_length_l+"", 16);
        msg[2] = (byte)Integer.parseInt(msg_length_h+"", 16);
        msg[3] = (byte) 0x86;
        byte[] temp = imei.getBytes();
        System.arraycopy(temp, 0, msg, 4, 15);//类型、imei
        System.arraycopy(downData, 0, msg, 19, downData.length);//类型、imei
        msg[msg_length-3] = ConvertUtils.getTotalForByte(msg);//校验和
        msg[msg_length-2] = 0x0d;
        msg[msg_length-1] = 0x0a;
		return  Unpooled.wrappedBuffer(msg);
	}

}
